package tester.component;

import tester.common.Constants;
import tester.entitys.JdbcInfo;
import tester.entitys.KafkaInfo;
import tester.entitys.TableInfo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;

public class Saver {
    public static final String prefix = "CheckPoint";
    public static final String filePrefix = "./src/main/resources/data/";
    public static final String fileSuffix =  ".txt";
    public static String getFilePath(String fileName) {
        return filePrefix + fileName + fileSuffix;
    }
    /**
     * 对于所有数据库表，按主键排序查找后并按tableName顺序输出到文件fileName中
     * @param suffixStr 输出文件名
     */
    public static void save(String suffixStr) {
        // 使用TreeMap自动按表名排序
        Map<String, List<String>> tableDataMap = new TreeMap<>();
        String filePath = getFilePath(suffixStr);
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
            // 遍历所有JDBC配置
            for (JdbcInfo info : Configer.JdbcMap.values()) {
                Connection conn = null;
                try {
                    Class.forName("oracle.jdbc.driver.OracleDriver");
                    // 获取数据库连接
                    conn = DriverManager.getConnection(info.getUrl(), info.getUser(), info.getPwd());

                    // 遍历当前数据库的所有表
                    for (TableInfo tableInfo : info.getTableInfos()) {
                        String tableName = tableInfo.getTableName();
                        System.out.println("正在处理数据库 " + info.getSign() + " 中的表 " + tableName);
                        List<String> keys = Arrays.stream(tableInfo.getUniqueKey().split("/.")).map(String::trim)
                                .collect(Collectors.toList());

                        // 查询表数据并按主键排序
                        List<String> tableData = queryTableData(conn, tableName, keys,info.getSign());
                        tableDataMap.put(tableName, tableData);
                    }
                } catch (SQLException e) {
                    System.err.println("处理数据库 " + info.getUrl() + " 时出错: " + e.getMessage());
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (conn != null) {
                        try {
                            conn.close();
                        } catch (SQLException e) {
                            System.err.println("关闭连接时出错: " + e.getMessage());
                        }
                    }
                }
            }

            // 将所有表数据按表名顺序写入文件
            System.out.println("正在将所有表数据写入文件 " + suffixStr);
            writeToFile(writer, tableDataMap);

        } catch (IOException e) {
            System.err.println("写入文件时出错: " + e.getMessage());
        }
    }

    /**
     * 查询表数据并按主键排序
     */
    private static List<String> queryTableData(Connection conn, String tableName, List<String> primaryKeys,
                                               String sign)
            throws SQLException {
        List<String> tableData = new ArrayList<>();

        if (primaryKeys.isEmpty()) {
            primaryKeys.add("1"); // 如果没有主键，使用伪列保证SQL语法正确
        }

        // 构建SQL查询语句
        String orderBy = primaryKeys.stream().collect(Collectors.joining(", "));
        String sql = "SELECT * FROM " + tableName + " ORDER BY " + orderBy;

        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {

            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();

            // 添加表头
            StringBuilder header = new StringBuilder();
            for (int i = 1; i <= columnCount; i++) {
                if (i > 1) header.append("|");
                header.append(metaData.getColumnName(i));
            }
            tableData.add("=== " + sign+"."+tableName + " ===");
            tableData.add(header.toString());
            //添加列类型
            StringBuilder type = new StringBuilder();
            for (int i = 1; i <= columnCount; i++) {
                if (i > 1) type.append("|");
                type.append(metaData.getColumnTypeName(i));
            }
            tableData.add(type.toString());
            // 添加数据行
            while (rs.next()) {
                StringBuilder row = new StringBuilder();
                for (int i = 1; i <= columnCount; i++) {
                    if (i > 1) row.append("|");
                    row.append(rs.getString(i) != null ? rs.getString(i) : "NULL");
                }
                tableData.add(row.toString());
            }
        }

        return tableData;
    }

    /**
     * 将表数据写入文件
     */
    private static void writeToFile(BufferedWriter writer, Map<String, List<String>> tableDataMap)
            throws IOException {
        for (Map.Entry<String, List<String>> entry : tableDataMap.entrySet()) {
            for (String line : entry.getValue()) {
                writer.write(line);
                writer.newLine();
            }
            writer.newLine(); // 表之间添加空行分隔
        }
    }
}
